package com.xinsoft.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.xinsoft.common.Response;
import com.xinsoft.constant.Const;
import com.xinsoft.entity.po.*;
import com.xinsoft.service.*;
import com.xinsoft.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SyncBasicAdapter {

    private SyncBasicService syncBasicService;

    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private SysDictionaryService sysDictionaryService;
    @Autowired
    private SysMaterialService sysMaterialService;
    @Autowired
    private MesBomService mesBomService;
    @Autowired
    private MesBomDetailService mesBomDetailService;
    @Autowired
    private SysWarehouseService sysWarehouseService;
    @Autowired
    private SysWarehouseItemService sysWarehouseItemService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysClientService sysClientService;
    @Autowired
    private SysSupplierService sysSupplierService;
    @Autowired
    private SysDeptService sysDeptService;
    @Autowired
    private SysConfigService configService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private SyncBasicKisServiceImpl syncBasicKisServiceImpl;
    @Autowired
    private SyncBasicU8ServiceImpl syncBasicU8ServiceImpl;

    private String ERP_CONNECT_TYPE;

    @PostConstruct
    private void init() {
        List<SysConfig> sysConfigDOS = configService.list(new LambdaQueryWrapper<SysConfig>()
                .eq(SysConfig::getParamKey, Const.ERP_CONNECT_URL).or().eq(SysConfig::getParamKey, Const.ERP_CONNECT_TYPE));
        sysConfigDOS.forEach(item ->{
            if ("ERP_CONNECT_TYPE".equals(item.getParamKey()))
                ERP_CONNECT_TYPE = item.getParamValue();
            if ("ERP_CONNECT_URL".equals(item.getParamKey()))
                redisUtil.set(Const.ERP_CONNECT_URL, item.getParamValue());
        });

        List<SysDictionary> timeFormat = sysDictionaryService.list(new LambdaQueryWrapper<SysDictionary>()
                .eq(SysDictionary::getDictionaryTypeId, 235).eq(SysDictionary::getDicName, "时间转换格式"));
        if (ObjectUtil.isNotEmpty(timeFormat)){
            redisUtil.set(Const.TIME_FORMAT, timeFormat.get(0).getDicValue());
        }

    }

    public Response<?> materielSync() {
        List<SysMaterial> sysMaterialDtos = new ArrayList<>();
        if (ERP_CONNECT_TYPE.equals("1")) sysMaterialDtos = syncBasicKisServiceImpl.materielSync();
        if (ERP_CONNECT_TYPE.equals("3")) sysMaterialDtos = syncBasicU8ServiceImpl.materielSync();
        if (ObjectUtil.isEmpty(sysMaterialDtos)) return Response.succeed();
        List<List<SysMaterial>> list = Lists.partition(sysMaterialDtos,100);
        list.forEach(item-> sysMaterialService.insertOrUpdateBatch(item));
        return Response.succeed();
    }

    public Response<?> unitSync() {
        sysDictionaryService.remove(new LambdaQueryWrapper<SysDictionary>().eq(SysDictionary::getDictionaryTypeId,1));
        List<SysDictionary> sysDictionaries = new ArrayList<>();
        if (ERP_CONNECT_TYPE.equals("1")) sysDictionaries = syncBasicKisServiceImpl.unitSync();
        if (ERP_CONNECT_TYPE.equals("3")) sysDictionaries = syncBasicU8ServiceImpl.unitSync();
        if (ObjectUtil.isEmpty(sysDictionaries)) return Response.succeed();
        sysDictionaryService.saveBatch(sysDictionaries);
        return Response.succeed();
    }

    public Response<?> bomSync() {
        Pair<List<MesBom>, List<MesBomDetail>> listListPair = Pair.of(new ArrayList<>(), new ArrayList<>());
        if (ERP_CONNECT_TYPE.equals("1")) listListPair = syncBasicKisServiceImpl.bomSync();
        if (ERP_CONNECT_TYPE.equals("3")) listListPair = syncBasicU8ServiceImpl.bomSync();
        List<MesBom> bomList = listListPair.getLeft();
        List<MesBomDetail> newBomDetail = listListPair.getRight();
        List<Integer> ids = bomList.stream().map(MesBom::getId).collect(Collectors.toList());
        List<MesBomDetail> oldBomDetail = mesBomDetailService.list(new LambdaQueryWrapper<MesBomDetail>().in(MesBomDetail::getBomId, ids));
        Map<String, Integer> oldBomDetailMap = oldBomDetail.stream().collect(Collectors.toMap(item -> item.getBomId().toString() + item.getRowIdKis(), item -> item.getId(), (v1, v2) -> v1));
        if (ObjectUtil.isNotEmpty(bomList)) {
            // mesBomService.saveOrUpdateBatch(listListPair.getLeft());
            mesBomService.insertOrUpdateBatch(listListPair.getLeft());
        }
        if (ObjectUtil.isNotEmpty(newBomDetail)) {
            newBomDetail.forEach(item->{
                String rowKis = item.getBomId().toString() + item.getRowIdKis();
                if (!oldBomDetailMap.containsKey(rowKis)) return;
                item.setId(oldBomDetailMap.get(rowKis));
            });
            // mesBomDetailService.saveOrUpdateBatch(listListPair.getRight());
            mesBomDetailService.insertOrUpdateBatch(listListPair.getRight());
        }
        return Response.succeed();
    }

    public Response<?> wareHouseSync() {
        Pair<List<SysWarehouse>, List<SysWarehouseItem>> listListPair = Pair.of(new ArrayList<>(), new ArrayList<>());
        if (ERP_CONNECT_TYPE.equals("1")) listListPair = syncBasicKisServiceImpl.wareHouseSync();
        if (ERP_CONNECT_TYPE.equals("3")) listListPair = syncBasicU8ServiceImpl.wareHouseSync();
        if (ObjectUtil.isNotEmpty(listListPair) || ObjectUtil.isNotEmpty(listListPair.getLeft())) {
            sysWarehouseService.remove(new LambdaQueryWrapper<SysWarehouse>().isNotNull(SysWarehouse::getId));
            sysWarehouseService.insertOrUpdateBatch(listListPair.getLeft());
        }
        List<SysWarehouseItem> itemList = listListPair.getRight();
        if (ObjectUtil.isEmpty(itemList)){
            return Response.succeed();
        }
        List<SysWarehouseItem> warehouseItemsDOS = new ArrayList<>();
        List<String> groups = itemList.stream().map(SysWarehouseItem::getGroupKis).distinct().collect(Collectors.toList());
        List<SysWarehouse> warehouseDOS = sysWarehouseService.list(new LambdaQueryWrapper<SysWarehouse>().in(SysWarehouse::getGroupKis, groups));
        Map<String, List<SysWarehouseItem>> itemListGroup = itemList.stream().collect(Collectors.groupingBy(SysWarehouseItem::getGroupKis));
        warehouseDOS.forEach(warehouse ->{
            List<SysWarehouseItem> items = itemListGroup.get(warehouse.getGroupKis());
            if (ObjectUtil.isEmpty(items)) return;
            //深拷贝
            List<SysWarehouseItem> itemTemps = JSON.parseArray(JSON.toJSONString(items), SysWarehouseItem.class);
            itemTemps.forEach(item -> item.setWarehouseId(warehouse.getId()));
            warehouseItemsDOS.addAll(itemTemps);
        });
        //todo 将数据库中的id主键去除
        sysWarehouseItemService.allDelete();
//        sysWarehouseItemService.remove(new LambdaQueryWrapper<SysWarehouseItem>().isNotNull(SysWarehouseItem::getId));
        sysWarehouseItemService.insertOrUpdateBatch(warehouseItemsDOS);
        return Response.succeed();
    }

    public Response<?> userSync() {
        List<SysUser> sysUserDtos = new ArrayList<>();
        if (ERP_CONNECT_TYPE.equals("1")) sysUserDtos = syncBasicKisServiceImpl.userSync();
        if (ERP_CONNECT_TYPE.equals("3")) sysUserDtos = syncBasicU8ServiceImpl.userSync();
        if (ObjectUtil.isEmpty(sysUserDtos)) return Response.succeed();
        List<com.xinsoft.entity.po.SysUser> allUserDOS = sysUserService.list();
        Map<Integer, com.xinsoft.entity.po.SysUser> userMap = allUserDOS.stream().collect(Collectors.toMap(item -> item.getId(), item -> item, (v1, v2) -> v1));
        sysUserDtos.stream().forEach(item -> {
            if(!userMap.containsKey(item.getId())) item.setPassword(passwordEncoder.encode("111111"));
        });
        // sysUserService.saveOrUpdateBatch(sysUserDtos);
        sysUserService.insertOrUpdateBatch(sysUserDtos);
        return Response.succeed();
    }

    public Response<?> clientSync() {
        List<SysClient> sysClientDtos = new ArrayList<>();
        if (ERP_CONNECT_TYPE.equals("1")) sysClientDtos = syncBasicKisServiceImpl.clientSync();
        if (ERP_CONNECT_TYPE.equals("3")) sysClientDtos = syncBasicU8ServiceImpl.clientSync();
        if (ObjectUtil.isEmpty(sysClientDtos)) return Response.succeed();
        // sysClientService.saveOrUpdateBatch(sysClientDtos);
        sysClientService.insertOrUpdateBatch(sysClientDtos);
        return Response.succeed();
    }

    public Response<?> supplierSync() {
        List<SysSupplier> sysSupplierDtos = new ArrayList<>();
        if (ERP_CONNECT_TYPE.equals("1")) sysSupplierDtos = syncBasicKisServiceImpl.supplierSync();
        if (ERP_CONNECT_TYPE.equals("3")) sysSupplierDtos = syncBasicU8ServiceImpl.supplierSync();
        if (ObjectUtil.isEmpty(sysSupplierDtos)) return Response.succeed();
        // sysSupplierService.saveOrUpdateBatch(sysSupplierDtos);
        sysSupplierService.insertOrUpdateBatch(sysSupplierDtos);
        return Response.succeed();
    }

    public Response<?> departSync() {
        List<SysDept> sysDeptDtos = new ArrayList<>();
        if (ERP_CONNECT_TYPE.equals("1")) sysDeptDtos = syncBasicKisServiceImpl.departSync();
        if (ERP_CONNECT_TYPE.equals("3")) sysDeptDtos = syncBasicU8ServiceImpl.departSync();
        if (ObjectUtil.isEmpty(sysDeptDtos)) return Response.succeed();
        // sysDeptService.saveOrUpdateBatch(sysDeptDtos);
        sysDeptService.insertOrUpdateBatch(sysDeptDtos);
        return Response.succeed();
    }

}
